package com.blog.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blog.admin.service.CategoryService;
import com.blog.common.core.exception.ServiceException;
import com.blog.common.core.utils.PageUtils;
import com.blog.common.core.web.page.TableDataInfo;
import com.blog.common.domain.entity.Article;
import com.blog.common.domain.entity.Category;
import com.blog.common.domain.dto.CategoryDto;
import com.blog.common.domain.dto.ConditionDto;
import com.blog.common.domain.vo.CategoryVo;
import com.blog.common.mapper.dao.ArticleMapper;
import com.blog.common.mapper.dao.CategoryMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

import static com.blog.common.core.constant.ServiceConst.DEFAULT_CATEGORY_ID;

/**
 * <p>
 * 分类 服务实现类
 * </p>
 *
 * @author Valerie
 * @since 2023-03-11
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private ArticleMapper articleMapper;

    @Override
    public List<CategoryVo> listCategoriesBySearch(ConditionDto condition) {
        List<Category> categoryList = new LambdaQueryChainWrapper<>(categoryMapper)
                .select(Category::getId, Category::getCategoryName)
                .like(StringUtils.isNotBlank(condition.getKeywords()), Category::getCategoryName, condition.getKeywords())
                .orderByDesc(Category::getId)
                .list();
        return BeanUtil.copyToList(categoryList, CategoryVo.class);
    }

    @Override
    public TableDataInfo<CategoryVo> listCategories(ConditionDto condition) {
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<Category>()
                .eq(condition.getPId() == null, Category::getPId, 0)
                .eq(condition.getPId() != null, Category::getPId, condition.getPId());
        List<Category> categoryList;
        long size;
        if (Objects.nonNull(condition.getByPage()) && !condition.getByPage()){
            Page categoryPage = categoryMapper.selectPage(PageUtils.getPage(), wrapper);
            categoryList = categoryPage.getRecords();
            size = categoryPage.getTotal();
        }else {
            categoryList = categoryMapper.selectList(wrapper);
            size = categoryList.size();
        }
        List<Long> pIdList = categoryList.stream().map(Category::getId).collect(Collectors.toList());
        List<Category> categorieChildList = new LambdaQueryChainWrapper<>(categoryMapper)
                .in(Category::getPId, pIdList)
                .list();
        List<CategoryVo> childList = BeanUtil.copyToList(categorieChildList, CategoryVo.class);
        List<CategoryVo> categoryVoList = BeanUtil.copyToList(categoryList, CategoryVo.class);
        Map<Long, List<CategoryVo>> childMap = childList.stream().collect(Collectors.groupingBy(CategoryVo::getPId));
        categoryVoList = categoryVoList.stream().peek(item -> item.setSubcategoryList(childMap.get(item.getId()))).collect(Collectors.toList());
        return new TableDataInfo<>(categoryVoList, size);
    }

    @Override
    public Boolean deleteCategories(Serializable categoryIds) {
        Set<Integer> categoryIdSet = Arrays.stream(categoryIds.toString().split(",")).map(Integer::parseInt).collect(Collectors.toSet());
        if (categoryIdSet.contains(DEFAULT_CATEGORY_ID)){
            return false;
        }
        this.remove(new LambdaQueryWrapper<Category>().in(Category::getId, categoryIdSet));
        new LambdaUpdateChainWrapper<>(articleMapper)
                .in(Article::getCategoryId, categoryIdSet)
                .set(Article::getCategoryId, DEFAULT_CATEGORY_ID)
                .update();
        return true;
    }

    @Override
    public CategoryVo saveCategories(CategoryDto categoryDto) {
        Category category = Category.builder()
                .categoryName(categoryDto.getCategoryName())
                .build();
        this.save(category);
        return BeanUtil.copyProperties(category, CategoryVo.class);
    }

    @Override
    public CategoryVo getCategoriesById(Serializable categoryId) {
        return BeanUtil.copyProperties(this.getById(categoryId), CategoryVo.class);
    }

    @Override
    public CategoryVo updateCategories(CategoryDto categoryDto) {
        if (Objects.equals(categoryDto.getId(), DEFAULT_CATEGORY_ID)){
            throw new ServiceException("无法修改默认分类 ！");
        }
        CategoryService categoryService = SpringUtil.getBean(CategoryService.class);
        Category category = BeanUtil.copyProperties(categoryDto, Category.class);
        categoryService.saveOrUpdate(category);
        return BeanUtil.copyProperties(category, CategoryVo.class);
    }
}
